//Copyright 2011 - Jonathan Allen

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Diagnostics.Contracts;
using System.Diagnostics.CodeAnalysis;

namespace Granite.Modeling.Internals
{
    /// <summary>
    /// Used to compare ValidationResults
    /// </summary>
    /// <remarks>
    /// This does not properly support subclasses 
    /// </remarks>
    [Pure]
    public class ValidationResultEqualityComparer : IEqualityComparer<ValidationResult>
    {
        [Pure]
        ValidationResultEqualityComparer()
        { }

        /// <summary>
        /// Performs a value comparison by looking at the error message and member names
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        /// <remarks>WARNING: The result of Equals can change! It is based on ValidationResult, which unfortunately isn't immutable.</remarks>
        [Pure]
        public bool Equals(ValidationResult x, ValidationResult y)
        {

            if (x == y)
                return true;

            if (x == null || y == null)
                return false;

            if (x.ErrorMessage != y.ErrorMessage)
                return false;

            if (x.MemberNames == y.MemberNames )
                return true;

            Contract.Assume(x.MemberNames != null); //The default implementation of this converts null member names into empty lists.
            Contract.Assume(y.MemberNames != null);

            return x.MemberNames.SequenceEqual(y.MemberNames);
        }

        /// <summary>
        /// Returns a hash code derived from the error message.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        /// <remarks>WARNING: The result of GetHashCode can change! It is based on ValidationResult, which unfortunately isn't immutable.</remarks>
        [Pure]
        public int GetHashCode(ValidationResult obj)
        {
            if (obj == null || obj.ErrorMessage == null)
                return 0;

            return obj.ErrorMessage.GetHashCode();
        }

        /// <summary>
        /// Returns the default instance of the comparer.
        /// </summary>
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
        public static readonly ValidationResultEqualityComparer Default = new ValidationResultEqualityComparer();
    }
}
